import React from 'react';
import { Pie, PieOptions } from '@antv/g2plot';
import { getComponentData } from 'src/services/AnalyseManage';
import { WD_TYPE, THEME_COLOR } from 'src/pages/AnalyseManage/EditReport/components/EditorDataType/EnumConfig';
import PubSub from 'pubsub-js';
import { CHART_LINK } from '../../../topics';
import { ChartService, IProps } from 'src/pages/AnalyseManage/EditReport/components/ChartsType/components/ChartService';
import { digitFormat } from 'src/libs/utils';

export default class PieChart extends ChartService {

	state = {
		data: [
			{ item: '事例一', count: 40, percent: 40 },
			{ item: '事例二', count: 21, percent: 21 },
			{ item: '事例三', count: 17, percent: 17 },
			{ item: '事例四', count: 13, percent: 13 },
			{ item: '事例五', count: 9, percent: 9 },
		],
		sourceData: [],	//	接口原数据
		chartEl: null,
		dataUnit: '',
		eventToken: [],		//	监听事件的token，用于销毁事件
		dependencies: [],	//	图表联动参数
		isRender: false, 	//	初始渲染标识
		drillDownConditions: [],		//	下钻参数
		drillDownDimension: []	// 当前需要下钻的维度
	};



	getConfig = (): PieOptions => {
		let { config } = this.props;
		return {
			data: this.state.data,
			radius: 0.75,
			innerRadius: this.props.config.data.pieType === 'circle' ? 0.6 : 0,	//	饼图 pie   环图 circle
			autoFit: true,
			angleField: 'percent',
			colorField: 'item',
			// 设置轴边距
			appendPadding: [
				config.style.chartTopPadding || 0,
				config.style.chartRightPadding || 0,
				config.style.chartBottomPadding || 0,
				config.style.chartLeftPadding || 0
			],
			color: ( config.style.customBlockColor || [] ).map( v => v.color ).concat( THEME_COLOR ),
			label: config.style.isShowLabel === false ? false : this.getLabelOptions( config.style ),
			legend: config.style.isShowLegend === true ? {
				position: config.style.legendPosition || 'bottom',
				flipPage: true,
				itemHeight: config.style.legendFontSize ? parseInt( config.style.legendFontSize ) : 15,
				background: {
					style: {
						stroke: null,
						height: config.style.legendFontSize ? parseInt( config.style.legendFontSize ) : 15,
					}
				},
				itemName: {
					style: {
						fill: config.style.legendFontColor || '#999',
						fontSize: config.style.legendFontSize || 15,
						fontFamily: config.style.legendFontFamily,
						fontWeight: config.style.legendFontBold ? 'bold' : 'normal',
						fontStyle: config.style.legendFontItalic ? 'italic' : 'normal'
					}
				}
			} : false,
			tooltip: {
				showTitle: false,
				showMarkers: false,
				fields: [ 'item', 'percent', 'count' ],
				formatter: ( { item, percent, count } ) => {
					percent = `${ percent }%`;
					count = digitFormat( count, 3 );
					let value = [];
					config.style.tooltipType && config.style.tooltipType.includes( 'percent' ) && value.push( percent );
					config.style.tooltipType && config.style.tooltipType.includes( 'count' ) && value.push( value.length > 0 ?
						`(${count}${this.state.dataUnit})` :
						`${count}${this.state.dataUnit}` );

					return {
						name: item,
						value: config.style.tooltipType ? value.join( '' ) : percent

					};
				},
				domStyles: {
					'g2-tooltip-list-item': {
						fontSize: `${ config.style.tooltipFontSize || '12' }px`,
						color: config.style.tooltipFontColor,
						fontFamily: config.style.tooltipFontFamily,
						fontWeight: config.style.tooltipFontBold ? 'bold' : 'normal',
						fontStyle: config.style.tooltipFontItalic ? 'italic' : 'normal'
					}
				},
				itemTpl: '<li class="g2-tooltip-list-item">{name}: {value}</li>'
			},
			interactions: [ { type: 'element-single-selected' } ],
			statistic: {
				title: false,
				content: false,
			},
		};
	}

	async getConditionData( drillX?: Array<any> ) {
		if ( this.props.config.data.pieDimension && this.props.config.data.pieDimension.length > 0 &&
			this.props.config.data.pieMeasure && this.props.config.data.pieMeasure.length > 0 ) {
			let x = [];

			//	如果是下钻
			if( drillX ) {
				x = drillX.concat( this.props.config.data.pieMeasure ).map( v => this.getFieldParams( v ) );
			} else {
				x = this.props.config.data.pieDimension.concat( this.props.config.data.pieMeasure ).map( v => this.getFieldParams( v ) );
			}

			// const conditions = this.props.config.data.filterFields ? this.props.config.data.filterFields.map( v => v.filterConditions ).flat() : [];
			// 内部筛选 condition
			const filterFieldCondition = this.props.config.data.filterFields
				? this.props.config.data.filterFields.map( ( v ) => v.filterConditions ).flat()
				: [];

			// 筛选组件的 condition
			let filterCompConditions = this.props.config.data.filterConditions || {};
			let newFilterCompConditions = [];
			Object.keys( filterCompConditions ).forEach( ( key ) => {
				newFilterCompConditions = newFilterCompConditions.concat( filterCompConditions[key] );
			} );

			const request = {

				dataConfig: {
					dataModel: {
						pageId: this.props.pageId,
						tableName: this.props.config.data.tableCode,
						x: x,
						conditions: filterFieldCondition.concat( newFilterCompConditions, this.state.dependencies, this.state.drillDownConditions )
					},
					needAutoRefresh: true,
					tableType: 'pie'
				},
				type: 'graphics',
				tenantCode: this.props.tenantCode
			};

			let pageResponse = await getComponentData( request );
			if ( pageResponse.data && pageResponse.data.success ) {
				//	将item组装
				const iData = pageResponse.data.data.rows.map( ( v, i ) => {
					return {
						count: v.count,
						percent: v.percent || 0,
						item: v.item.join( '-' ),
						index: i     					//	用于图表联动，查找数据索引
					};
				} );

				const dataUnit = pageResponse.data.data.rows.length > 0 ? pageResponse.data.data.rows[0].dataUnit || '' : '';

				this.setState( {
					data: iData,
					sourceData: pageResponse.data.data.rows,
					dataUnit: dataUnit
				} );
			}
		}


	}

	initEvent = async () => {
		await this.getConditionData();

		const chartEl: any = new Pie( this.props.id, this.getConfig() );

		chartEl.render();

		this.setState( {
			chartEl: chartEl,
			isRender: true
		} );

		//	数据联动 组装联动参数
		chartEl.on( 'interval:click', async ( ev ) => {
			const intervalElement = ev.target.get( 'element' );
			const data = intervalElement.getModel().data; // 单条数据

			let dimension = [];
			if( this.props.config.mutual.isDrillDown && this.state.drillDownDimension.length > 0 ) {
				dimension = this.state.drillDownDimension;
			} else {
				dimension = this.props.config.data.pieDimension;
			}

			if( !dimension || dimension.length === 0 ) return;
			const dependencies = dimension.map( ( item, index ) => {
				return {
					formatType: item.formatType,
					id: [ item.name ],
					quota: item.modelType === WD_TYPE ? 'WD' : 'DL',
					symbol: 'EQ',
					value: [ this.state.sourceData[data.index].item[index] ]		//	从原数据中找到item，一一对应字段
				};
			} );

			//	如果开启下钻
			if( this.props.config.mutual.isDrillDown ) {
				this.handleDrillDown( dimension, dependencies );
			}

			if ( this.props.config.mutual.isChainAvailable ) {
				PubSub.publish( CHART_LINK, {
					publisherId: this.props.id,
					listenerIds: this.props.config.mutual.chartsChainIds,
					dimension: dependencies,
					tableCode: this.props.config.data.tableCode
				} );
			}

		} );
	};

	getLabelOptions = ( style ) => {
		return {

			content: ( data ) => {
				const array = [];
				!style.labelContentType && array.push( `${ ( data.percent * 100 ).toFixed( 0 ) }%` );
				style.labelContentType && style.labelContentType.includes( 'item' ) && array.push( data.item );
				style.labelContentType && style.labelContentType.includes( 'count' ) && array.push( `${digitFormat( data.count, 3 )}${this.state.dataUnit}` );
				style.labelContentType && style.labelContentType.includes( 'percent' ) && array.push( `${ ( data.percent * 100 ).toFixed( 0 ) }%` );
				return array.length > 0 ? array.join( ',' ) : '';
			},
			offset: style.labelPosition === 'inner' ? '-40%' : 20,
			type: style.labelPosition === 'spider' ? 'spider' : '' as any,
			labelLine: {
				style: {
					stroke: style.chartLabelLineColor || '#999',
				},
			},
			style: {
				textAlign: 'center',
				fontFamily: '',
				fontSize: style.labelFontSize || 14,
				fill: style.labelFontColor || '#999',
				fontWeight: style.labelFontBold ? 'bold' : 'normal',
				fontStyle: style.labelFontItalic ? 'italic' : 'normal'
			}

		};
	};

	shouldComponentUpdate( nextProps: Readonly<IProps>, nextState: Readonly<any>, nextContext: any ): boolean {
		if ( JSON.stringify( nextProps ) !== JSON.stringify( this.props ) ||
			JSON.stringify( this.state.dependencies ) !== JSON.stringify( nextState.dependencies )
		) return true;
		return false;
	}

	getSnapshotBeforeUpdate( prevProps: Readonly<IProps>, prevState: Readonly<any> ): any | null {
		let { config, chartLayout } = this.props;
		let changeObj = Object.create( null );

		//	判断数据字段是否变化了
		if ( JSON.stringify( prevProps.config.data.pieDimension ) !== JSON.stringify( config.data.pieDimension ) ||
			JSON.stringify( prevProps.config.data.pieMeasure ) !== JSON.stringify( config.data.pieMeasure ) ||
			JSON.stringify( prevProps.config.data.filterFields ) !== JSON.stringify( config.data.filterFields ) ||
			JSON.stringify( prevProps.config.data.filterConditions ) !== JSON.stringify( config.data.filterConditions ) ||
			JSON.stringify( this.state.dependencies ) !== JSON.stringify( prevState.dependencies )
		) {
			changeObj.needDataChange = true;
		}

		//	判断样式是否改变
		if ( JSON.stringify( prevProps.config.style ) !== JSON.stringify( config.style ) ||
			prevProps.config.data.pieType !== config.data.pieType ) {
			changeObj.needStyleChange = true;
		}

		//判断是否因宽高改变重新适应布局
		if ( prevProps.chartLayout.w !== chartLayout.w || prevProps.chartLayout.h !== chartLayout.h ) {
			changeObj.needLayoutChange = true;
		}

		//	判断是否需要清除下钻
		if(
			( prevProps.config.mutual.isDrillDown && !this.props.config.mutual.isDrillDown ) ||
			( prevProps.drillChartsIds.includes( this.props.id ) && !this.props.drillChartsIds.includes( this.props.id ) )
		) {
			changeObj.needClearDrill = true;
		}

		return changeObj;

	}

	async componentDidUpdate( prevProps: Readonly<IProps>, prevState: Readonly<{}>, snapshot?: any ) {

		//	如果数据条件改变，则获取数据
		if (
			(
				snapshot.needDataChange &&
				this.props.config.data.pieDimension && this.props.config.data.pieDimension.length > 0 &&
				this.props.config.data.pieMeasure && this.props.config.data.pieMeasure.length > 0
			) || snapshot.needClearDrill
		) {

			//	同步更新数据
			setTimeout( async () => {
				this.clearDrill();

				await this.getConditionData();

				this.state.chartEl.changeData( this.state.data );
			}, 0 );
		}

		if ( snapshot.needStyleChange ) {
			this.state.chartEl.update( this.getConfig() );
		}
	}

	render() {
		return (
			<div id={ this.props.id } style={ { height: '100%' } }></div>
		);
	}
}
